package ar.edu.unq.persistencia.commands;

import java.util.ArrayList;
import java.util.List;

import org.hibernate.CacheMode;
import org.hibernate.Criteria;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projection;
import org.hibernate.criterion.ProjectionList;
import org.hibernate.criterion.Projections;
import org.hibernate.transform.Transformers;

/**
 * TODO: description
 */
public class ObtenerEntidadCommand<T> extends Command<T> {

    private List<T> result;

    private List lista;

    private List<Criterion> criterions = new ArrayList<Criterion>();

    private List<Order> orders = new ArrayList<Order>();

    private ProjectionList projections = Projections.projectionList();;

    private Class clazz = null;

    public List<Order> getOrders() {
        return this.orders;
    }

    public void setOrders(final List<Order> orders) {
        this.orders = orders;
    }

    public ProjectionList getProjections() {
        return this.projections;
    }

    public void Projections(final Projection projection) {
        this.projections.add(projection);
    }

    public void setProjections(final ProjectionList projections) {
        this.projections = projections;
    }

    protected List<Criterion> getCriterions() {
        return this.criterions;
    }

    protected void setCriterions(final List<Criterion> criterions) {
        this.criterions = criterions;
    }

    public void addCriterion(final Criterion criterion) {
        this.getCriterions().add(criterion);
    }

    public void addProjection(final Projection projection) {
        this.getProjections().add(projection);
    }

    public void addOrder(final Order order) {
        this.addOrder(order);
    }

    public List<T> getResult() {
        return this.result;
    }

    public void setResult(final List<T> result) {
        this.result = result;
    }

    public ObtenerEntidadCommand(final Class clazz) {
        super(clazz);
    }

    public void setTranformer(final Class clazz) {
        this.clazz = clazz;
    }

    @SuppressWarnings("unchecked")
    public void run() {

        this.setObjectResult(this.buildCriteria().list());
        this.setResult(this.getObjectResult());
        // this.setResult(this.buildCriteria().list());
    }

    public List getObjectResult() {
        return this.lista;
    }

    public void setObjectResult(final List objects) {
        this.lista = objects;
    }

    private Criteria buildCriteria() {
        Criteria criteria = this.getSession().createCriteria(this.getClazz());
        this.getSession().setCacheMode(CacheMode.GET);
        criteria.setCacheable(true);
        this.setCriterionsToCriteria(criteria);

        this.setOrderToCriteria(criteria);

        this.setProjectionsToCriteria(criteria);
        if (this.clazz != null) {
            criteria.setResultTransformer(Transformers.aliasToBean(this.clazz));
        }

        return criteria;
    }

    private void setProjectionsToCriteria(final Criteria criteria) {
        if (this.getProjections().getLength() > 0) {
            criteria.setProjection(this.getProjections());
        }
    }

    private void setOrderToCriteria(final Criteria criteria) {
        for (Order order : this.getOrders()) {
            criteria.addOrder(order);
        }
    }

    private void setCriterionsToCriteria(final Criteria criteria) {
        for (Criterion criterion : this.getCriterions()) {
            criteria.add(criterion);
        }
    }

}
